// JsSiteHelper.cpp : Implementation of CJsSiteHelper

#include "stdafx.h"

#include <string>
#include <vector>
#include <algorithm>

#include "JsSiteHelper.h"

#include <cv.h>
#include <highgui.h>

#ifdef _DEBUG
#pragma comment(lib, "cxcore210d.lib")
#pragma comment(lib, "cv210d.lib")
#pragma comment(lib, "highgui210d.lib")
#else
#pragma comment(lib, "cxcore210.lib")
#pragma comment(lib, "cv210.lib")
#pragma comment(lib, "highgui210.lib")
#endif

using std::string;
using std::vector;
using std::sort;

//This is a helper class
typedef struct _CCompableCvRect : CvRect
{
	bool operator<(const _CCompableCvRect& rect1) const
	{
		return x < rect1.x;
	}
} CCompableCvRect;


STDMETHODIMP CJsSiteHelper::GernerateLink(const CHAR* pcFileId, const CHAR* pcSecIP, const CHAR* pcCaptcha, CHAR* pcRetURL)
{
	//Got the time second for 1970.1.1
	__time64_t time_now = ::_time64(NULL);
	
	//Create a rand double number under 1
	::srand(::_time32(NULL));
	double dbRand = (DOUBLE)::rand()/(RAND_MAX+1);
	
	//We Extend the rand 3 digitals, and got a proper time number
	time_now = time_now*1000+ (__time64_t)(dbRand*1000);

	//Convert the timestamp to string
	char pcTimeStamp[32] = { 0 };
	::_i64toa(time_now, pcTimeStamp, 10);
	
	//Gernerate a float rand number
	char pcRand[32] = { 0 };
	::sprintf(pcRand, "%1.16f", dbRand);

	string strURL = "http://hidamari.tora.to:8381/downloadserver/discutter/pagination.htm?r=";
	strURL += pcRand;
	strURL += "&dispatch=normaldownlaod&fileId=";
	strURL += pcFileId;
	strURL += "&ip=";
	strURL += pcSecIP;
	strURL += "&tid=1&captcha=";

	if(pcCaptcha != NULL)
	{
		strURL += pcCaptcha;
	}
	else
	{
		strURL += "undefined";
	}

	strURL += "&_=";
	strURL += pcTimeStamp;

	::strcpy(pcRetURL, strURL.c_str());

	return S_OK;
}

STDMETHODIMP CJsSiteHelper::ReadCaptchaFromImage(const CHAR* pcFilePath, CHAR* pcCaptchaStrig)
{
	//We Use OpenCV to Indentify the image
	IplImage* img = 0;
	IplImage* dst_img = 0; 
	IplImage* mono_img = 0;
	
	int height,width,step,channels,btsize;
	uchar *data;

	// load an image  
	img = cvLoadImage(pcFilePath);
	if(!img)
	{
		return S_FALSE;
	} 

	// get the image data
	height    = img->height;
	width     = img->width;
	step      = img->widthStep;
	channels  = img->nChannels;
	data      = (uchar *)img->imageData;
	btsize	= img->imageSize;

	dst_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
	cvCvtColor(img, dst_img, CV_RGB2GRAY); 

	mono_img = cvCreateImage(cvGetSize(dst_img),IPL_DEPTH_8U,1);

	IplImage* rect_mono = cvCreateImage(cvGetSize(dst_img),IPL_DEPTH_8U,1);

	cvThreshold(dst_img, rect_mono, 128, 255, CV_THRESH_BINARY_INV);
	cvThreshold(dst_img, mono_img, 128, 255, CV_THRESH_BINARY);

	CvMemStorage *stor = 0;
	CvSeq * cont = 0;
	CvSeq * a_contour= 0;

	stor = cvCreateMemStorage(0);
	cont = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), stor);
	int iobj = cvFindContours( rect_mono, stor, &cont, sizeof(CvContour), CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));

	vector<CCompableCvRect> vtAllRect;
	IplImage* tm_img[4];

	for(int i=0; cont; cont = cont->h_next, i++)
	{
		CCompableCvRect* prectChar;
		prectChar = static_cast<CCompableCvRect*>(&cvBoundingRect(cont));
		vtAllRect.push_back(*prectChar);
	}

	//If we did not found 4 digitals, we assume of failure
	if(vtAllRect.size() < 4)
	{
		cvReleaseImage(&img);
		cvReleaseImage(&dst_img);
		cvReleaseImage(&mono_img);
		cvReleaseImage(&rect_mono);

		//We Set a default captcah
		::strcpy(pcCaptchaStrig, "1234");
		return S_FALSE;
	}

	::sort(vtAllRect.begin(), vtAllRect.end());

	IplImage* imgTemplate = cvLoadImage("SitePatterns\\TARTemplateImage.bmp", -1);
	string strOCRResult;

	for(int i=0; i<4; i++)
	{
		cvSetImageROI(mono_img, vtAllRect[i]);

		tm_img[i] = cvCreateImage(cvSize(vtAllRect[i].width, vtAllRect[i].height), mono_img->depth, mono_img->nChannels);

		cvCopy(mono_img, tm_img[i], NULL);
		cvResetImageROI(mono_img);

		IplImage* pt_res = cvCreateImage(cvSize(imgTemplate->width - tm_img[i]->width + 1, imgTemplate->height - tm_img[i]->height + 1), IPL_DEPTH_32F, 1);
		cvMatchTemplate(imgTemplate, tm_img[i], pt_res, CV_TM_SQDIFF);

		CvPoint    minloc, maxloc;
		double    minval, maxval;
		cvMinMaxLoc(pt_res, &minval, &maxval, &minloc, &maxloc, 0);

		char cChar[3];
		::_itoa(minloc.x / 17, cChar, 10);
		strOCRResult += cChar;

		cvReleaseImage(&pt_res);
	}

	//return the result
	::strcpy(pcCaptchaStrig, strOCRResult.c_str());

	// release the image
	cvReleaseImage(&img);
	cvReleaseImage(&dst_img);
	cvReleaseImage(&mono_img);
	cvReleaseImage(&rect_mono);

	cvReleaseImage(&imgTemplate);

	for(int i=0; i<4; i++)
	{
		cvReleaseImage(&tm_img[i]);
	}

	return S_OK;
}
